/* $Id: ClientRegistrationFacadeImpl.java 
 * Copyright (C) 2011, TRAKHEES
 *  
 * Revision History
 *
 * Date  			Author 		    	Remarks
 * ---------------------------------------------------------------------------------
 *
 */
package ae.pcfc.etks.online.common.facade.provider;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.ConstantsCommon.WorkflowDepartment;
import ae.pcfc.etks.online.common.domain.AppMetaData;
import ae.pcfc.etks.online.common.domain.Client;
import ae.pcfc.etks.online.common.domain.ClientRoleReq;
import ae.pcfc.etks.online.common.domain.ClientServiceRole;
import ae.pcfc.etks.online.common.domain.ProcStepAthmnt;
import ae.pcfc.etks.online.common.domain.ServiceRole;
import ae.pcfc.etks.online.common.domain.TTscClientCompany;
import ae.pcfc.etks.online.common.domain.TTscClientPerson;
import ae.pcfc.etks.online.common.domain.TTscClientRole;
import ae.pcfc.etks.online.common.domain.TTscClientRoleToDepartmentMap;
import ae.pcfc.etks.online.common.domain.TTscDepartments;
import ae.pcfc.etks.online.common.domain.TTscLicIssuingAuthority;
import ae.pcfc.etks.online.common.domain.User;
import ae.pcfc.etks.online.common.domain.UserReq;
import ae.pcfc.etks.online.common.domain.UserServiceSecurity;
import ae.pcfc.etks.online.common.domain.manager.AppMetaDataDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.AttachmentTypeDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ClientDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ProcessDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ProcessStepActionDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.ServiceDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientCompanyDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientPersonDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientRoleObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UserDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UserReqDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UserServiceSecurityDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UtilityDomainObjectManager;
import ae.pcfc.etks.online.common.exception.DuplicateClientAdminException;
import ae.pcfc.etks.online.common.exception.DuplicateRoleRequestException;
import ae.pcfc.etks.online.common.exception.DuplicateUserNameException;
import ae.pcfc.etks.online.common.exception.InvalidInputException;
import ae.pcfc.etks.online.common.exception.TscClientLicenseInfoException;
import ae.pcfc.etks.online.common.facade.ClientRegistrationFacade;
import ae.pcfc.etks.online.common.vo.AdminApprovalVO;
import ae.pcfc.etks.online.common.vo.AppMetaDataDetailVO;
import ae.pcfc.etks.online.common.vo.ClientCompanyReqVO;
import ae.pcfc.etks.online.common.vo.ClientCompanyVO;
import ae.pcfc.etks.online.common.vo.ClientPersonReqVO;
import ae.pcfc.etks.online.common.vo.ClientPersonVO;
import ae.pcfc.etks.online.common.vo.ClientRoleVO;
import ae.pcfc.etks.online.common.vo.CompanyDetailVO;
import ae.pcfc.etks.online.common.vo.CompanySearchCriteriaVO;
import ae.pcfc.etks.online.common.vo.CompanySearchVO;
import ae.pcfc.etks.online.common.vo.IPageVO;
import ae.pcfc.etks.online.common.vo.SCClientCompanyRoleVO;
import ae.pcfc.etks.online.common.vo.SCClientPersonRoleVO;
import ae.pcfc.etks.online.common.vo.SCCompanyVO;
import ae.pcfc.etks.online.common.vo.SCPersonVO;
import ae.pcfc.etks.online.common.vo.SearchCriteriaCompanyVO;
import ae.pcfc.etks.online.common.vo.SearchCriteriaPersonVO;
import ae.pcfc.etks.online.common.vo.TrakheesIdAndPINVO;
import ae.pcfc.etks.online.common.vo.UploadDocumentVO;
import ae.pcfc.etks.online.common.vo.UserVO;
import ae.pcfc.etks.online.wf.ConstantsWF;
import ae.pcfc.etks.online.wf.service.client.ClientAdminWF;
import ae.pcfc.etks.online.wf.service.client.ClientRoleWF;
import ae.pcfc.etks.online.wf.service.client.vo.ClientRoleCompleteStepVO;
import ae.pcfc.etks.online.wf.service.client.vo.LaunchIncidentVO;

public class ClientRegistrationFacadeImpl extends BaseFacade implements ClientRegistrationFacade {
	/*
	 * Here we coordinate between the all interacting business domain objects
	 * (BO), transactions are maintained here. use case business validation are
	 * maintained here (that requires DB checks or retrieving data from DB)
	 */
	private UserReqDomainObjectManager userReqDomainObjectManager;
	private ProcessDomainObjectManager processDomainObjectManager;
	private AttachmentTypeDomainObjectManager attachmentTypeDomainObjectManager;
	private AppMetaDataDomainObjectManager appMetaDataDomainObjectManager;
	private SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager;
	private SingleClientCompanyDomainObjectManager singleClientCompanyDomainObjectManager;
	private ClientDomainObjectManager clientDomainObjectManager;
	private UtilityDomainObjectManager utilityDomainObjectManager;
	private SingleClientRoleObjectManager singleClientRoleObjectManager;
	private ServiceDomainObjectManager serviceDomainObjectManager;
	private UserServiceSecurityDomainObjectManager userServiceSecurityDomainObjectManager;
	private UserDomainObjectManager userDomainObjectManager;
	private ClientAdminWF clientPersonAdminWF;
	private ClientAdminWF clientCompanyAdminWF;
	private ClientRoleWF clientRoleWF;
	//private UserAnnouncementDomainObjectManager userAnnouncementDomainObjectManager;
	private ProcessStepActionDomainObjectManager processStepActionDomainObjectManager;

	public ProcessStepActionDomainObjectManager getProcessStepActionDomainObjectManager() {
		return processStepActionDomainObjectManager;
	}

	public void setProcessStepActionDomainObjectManager(
			ProcessStepActionDomainObjectManager processStepActionDomainObjectManager) {
		this.processStepActionDomainObjectManager = processStepActionDomainObjectManager;
	}

	public void setSingleClientCompanyDomainObjectManager(
			SingleClientCompanyDomainObjectManager singleClientCompanyDomainObjectManager) {
		this.singleClientCompanyDomainObjectManager = singleClientCompanyDomainObjectManager;
	}

	public void setUserReqDomainObjectManager(UserReqDomainObjectManager userReqDomainObjectManager) {
		this.userReqDomainObjectManager = userReqDomainObjectManager;
	}

	public void setProcessDomainObjectManager(ProcessDomainObjectManager processDomainObjectManager) {
		this.processDomainObjectManager = processDomainObjectManager;
	}

	public void setAttachmentTypeDomainObjectManager(AttachmentTypeDomainObjectManager attachmentTypeDomainObjectManager) {
		this.attachmentTypeDomainObjectManager = attachmentTypeDomainObjectManager;
	}

	public void setAppMetaDataDomainObjectManager(AppMetaDataDomainObjectManager appMetaDataDomainObjectManager) {
		this.appMetaDataDomainObjectManager = appMetaDataDomainObjectManager;
	}

	public void setSingleClientPersonDomainObjectManager(
			SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager) {
		this.singleClientPersonDomainObjectManager = singleClientPersonDomainObjectManager;
	}

	public void setClientDomainObjectManager(ClientDomainObjectManager clientDomainObjectManager) {
		this.clientDomainObjectManager = clientDomainObjectManager;
	}

	public void setUtilityDomainObjectManager(UtilityDomainObjectManager utilityDomainObjectManager) {
		this.utilityDomainObjectManager = utilityDomainObjectManager;
	}

	public void setSingleClientRoleObjectManager(SingleClientRoleObjectManager singleClientRoleObjectManager) {
		this.singleClientRoleObjectManager = singleClientRoleObjectManager;
	}

	public void setServiceDomainObjectManager(ServiceDomainObjectManager serviceDomainObjectManager) {
		this.serviceDomainObjectManager = serviceDomainObjectManager;
	}

	public void setUserServiceSecurityDomainObjectManager(
			UserServiceSecurityDomainObjectManager userServiceSecurityDomainObjectManager) {
		this.userServiceSecurityDomainObjectManager = userServiceSecurityDomainObjectManager;
	}

	public void setUserDomainObjectManager(UserDomainObjectManager userDomainObjectManager) {
		this.userDomainObjectManager = userDomainObjectManager;
	}

	public void setClientPersonAdminWF(ClientAdminWF clientPersonAdminWF) {
		this.clientPersonAdminWF = clientPersonAdminWF;
	}

	public void setClientCompanyAdminWF(ClientAdminWF clientCompanyAdminWF) {
		this.clientCompanyAdminWF = clientCompanyAdminWF;
	}

	public void setClientRoleWF(ClientRoleWF clientRoleWF) {
		this.clientRoleWF = clientRoleWF;
	}

/*	public void setUserAnnouncementDomainObjectManager(UserAnnouncementDomainObjectManager userAnnouncementDomainObjectManager) {
		this.userAnnouncementDomainObjectManager = userAnnouncementDomainObjectManager;
	}*/

	/**
	 * registerCompany
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#registerCompany(ae.pcfc.etks.online.common.vo.ClientCompanyReqVO)
	 * 
	 */
	@Transactional(readOnly = false)
	public String registerCompany(ClientCompanyReqVO clientCompanyReqVO) {
		/*if (validateRegisterCompany(clientCompanyReqVO)) {*/
			AppMetaData appMetaData = new AppMetaData();
			ae.pcfc.etks.online.common.domain.Process process = processDomainObjectManager.getProcessByProcessAndStepCode(
					clientCompanyReqVO.getProcessCode().getProcessCode(), clientCompanyReqVO.getStrProcessStep());

			appMetaData.setProcess(process);

			getMapper().map(clientCompanyReqVO, appMetaData);

			/***
			 * Mapper is not used because i have to set the attachment types
			 * which are in the nested entity
			 ***/
			Set<ProcStepAthmnt> procStepAtmnt = new HashSet<ProcStepAthmnt>();
			List<UploadDocumentVO> documentVOs = clientCompanyReqVO.getArrDocumentVOs();
			ProcStepAthmnt athmnt;

			for (UploadDocumentVO documentVO : documentVOs) {
				athmnt = new ProcStepAthmnt();
				athmnt.setAppMetaData(appMetaData);
				// Can we do this?
				athmnt.setProcessStep(process.getProcessSteps().iterator().next());
				athmnt.setAttachmentType(attachmentTypeDomainObjectManager.getAttachmentTypeByAttachmentCode(documentVO
						.getStrUploadDocumentType()));
				athmnt.setAttachmentPath(documentVO.getURL());
				procStepAtmnt.add(athmnt);
			}

			if (procStepAtmnt.size() > 0)
				appMetaData.setProcStepAthmnts(procStepAtmnt);

			appMetaDataDomainObjectManager.add(appMetaData);

			UserReq userReq = new UserReq();

			getMapper().map(clientCompanyReqVO, userReq);
			userReq.setApplicationId(appMetaData.getApplicationId());
			userReq.setUReqStatus(ConstantsCommon.IN_PROGRESS);

			this.userReqDomainObjectManager.add(userReq);

			return appMetaData.getClientRefNo();
		/*} else {
			return null;
		}*/
	}

	/**
	 * getCompanyRegisteration
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#getCompanyRegisteration(ae.pcfc.etks.online.common.vo.CompanySearchVO)
	 * 
	 */
	public CompanyDetailVO getCompanyRegisteration(CompanySearchVO companySearchVO) {
		// TODO Auto-generated method stub

		// companyDomainObjectManager.add(obj)
		return null;
	}

	/**
	 * searchCompanyRegisterationList
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#searchCompanyRegisterationList(ae.pcfc.etks.online.common.vo.CompanySearchCriteriaVO)
	 * 
	 */
	public IPageVO searchCompanyRegisterationList(CompanySearchCriteriaVO companySearchCriteriaVO) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * registerPerson
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#registerPerson(ae.pcfc.etks.online.common.vo.ClientPersonReqVO)
	 * 
	 */
	@Transactional(readOnly = false)
	public String registerPerson(ClientPersonReqVO clientPersonReqVO) {
		/*if (validateRegisterPerson(clientPersonReqVO)) {*/
			AppMetaData appMetaData = new AppMetaData();

			ae.pcfc.etks.online.common.domain.Process process = processDomainObjectManager.getProcessByProcessAndStepCode(
					clientPersonReqVO.getProcessCode().getProcessCode(), clientPersonReqVO.getStrProcessStep());

			appMetaData.setProcess(process);

			getMapper().map(clientPersonReqVO, appMetaData);

			/***
			 * Mapper is not used because i have to set the attachment types
			 * which are in the nested entity
			 ***/
			Set<ProcStepAthmnt> procStepAtmnt = new HashSet<ProcStepAthmnt>();
			List<UploadDocumentVO> documentVOs = clientPersonReqVO.getArrDocumentVOs();
			ProcStepAthmnt athmnt;

			for (UploadDocumentVO documentVO : documentVOs) {
				athmnt = new ProcStepAthmnt();
				athmnt.setAppMetaData(appMetaData);
				// Can we do this?
				athmnt.setProcessStep(process.getProcessSteps().iterator().next());
				athmnt.setAttachmentType(attachmentTypeDomainObjectManager.getAttachmentTypeByAttachmentCode(documentVO
						.getStrUploadDocumentType()));
				athmnt.setAttachmentPath(documentVO.getURL());
				procStepAtmnt.add(athmnt);
			}

			if (procStepAtmnt.size() > 0)
				appMetaData.setProcStepAthmnts(procStepAtmnt);

			appMetaDataDomainObjectManager.add(appMetaData);

			UserReq userReq = new UserReq();

			getMapper().map(clientPersonReqVO, userReq);
			userReq.setApplicationId(appMetaData.getApplicationId());
			userReq.setUReqStatus(ConstantsCommon.IN_PROGRESS);

			this.userReqDomainObjectManager.add(userReq);

			return appMetaData.getClientRefNo();
		/*} else {
			return null;
		}*/

	}

	/**
	 * validateTrakheesIdAndPIN
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#validateTrakheesIdAndPIN(ae.pcfc.etks.online.common.vo.TrakheesIdAndPINVO)
	 * 
	 */
	@Transactional(readOnly = true)
	public boolean validateTrakheesIdAndPIN(TrakheesIdAndPINVO idAndPINVO) {
		return this.singleClientPersonDomainObjectManager.validateTrakheesIdAndPIN(idAndPINVO);

	}

	/**
	 * findSCPersonByTrakheesId
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#findSCPersonByTrakheesId(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public SCPersonVO findSCPersonByTrakheesId(String trakheesId) {
		TTscClientPerson clientPerson = this.singleClientPersonDomainObjectManager.findSCPersonByTrakheesId(trakheesId);
		SCPersonVO scPersonVO = null;

		if (clientPerson != null) {
			scPersonVO = new SCPersonVO();
			getMapper().map(clientPerson, scPersonVO);

			List<SCClientPersonRoleVO> personRoleVOs = this.singleClientPersonDomainObjectManager
					.findSCPersonRoleByTrakheesId(trakheesId);

			if (personRoleVOs != null && personRoleVOs.size() > 0)
				scPersonVO.setSCClientPersonRoleVO(personRoleVOs);
		}

		return (scPersonVO != null) ? scPersonVO : null;

	}
	
	/**
	 * findSCCompanyByTrakheesId
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#findSCCompanyByTrakheesId(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public SCCompanyVO findSCCompanyByTrakheesId(String trakheesId) {

		TTscClientCompany clientCompany = this.singleClientCompanyDomainObjectManager.findSCCompanyByTrakheesId(trakheesId);

		SCCompanyVO scCompanyVO = null;

		if (clientCompany != null) 
		{
			scCompanyVO = new SCCompanyVO();
			getMapper().map(clientCompany, scCompanyVO);

			List<SCClientCompanyRoleVO> companyRoleVOs = this.singleClientCompanyDomainObjectManager
					.findSCCompanyRoleByTrakheesId(trakheesId);

			if (companyRoleVOs != null && companyRoleVOs.size() > 0)
				scCompanyVO.setSCClientCompanyRoleVO(companyRoleVOs);
			
			if(clientCompany.getCcLicIssuingAuthority() != null)
			{
				
				TTscLicIssuingAuthority licIssuingAuthority =  this.utilityDomainObjectManager.getLicIssuingAuthorityByCode(clientCompany.getCcLicIssuingAuthority());
			
				getMapper().map(licIssuingAuthority, scCompanyVO);
			}
			
		
		}

		return (scCompanyVO != null) ? scCompanyVO : null;

	}

	/**
	 * findClientPersonByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#findClientPersonByUserName(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public ClientPersonVO findClientPersonByUserName(String userName) {

		Client client = this.clientDomainObjectManager.findClientByUserName(userName);

		if (client != null) {
			ClientPersonVO clientPersonVO = new ClientPersonVO();
			getMapper().map(client, clientPersonVO);
			return clientPersonVO;
		} else
			return null;
	}

	/**
	 * findClientCompanyByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#findClientCompanyByUserName(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public ClientCompanyVO findClientCompanyByUserName(String userName) {

		Client client = this.clientDomainObjectManager.findClientByUserName(userName);

		if (client != null) {
			ClientCompanyVO clientCompanyVO = new ClientCompanyVO();
			getMapper().map(client, clientCompanyVO);
			return clientCompanyVO;
		} else
			return null;
	}

	/**
	 * updatePerson
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#updatePerson(ae.pcfc.etks.online.common.vo.UserVO)
	 * 
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Transactional
	public void updatePerson(UserVO userVO) {

		if (userVO != null) {
			Client client = this.clientDomainObjectManager.findClientByUserName(userVO.getStrUsrName());

			User user = null;

			if (client.getUsers() != null && client.getUsers().size() > 0)
				user = client.getUsers().iterator().next();

			if (user != null)
				getMapper().map(userVO, user);

			client.setUsers(new HashSet(Arrays.asList(user)));

			this.clientDomainObjectManager.update(client);
		}
	}
	/**
	 * Description:
	 * updateCompany:	Method to update the User information
	 * 
	 * @param	userVO UserVO
	 * @return 	-
	 * 					   
	 */
	@Transactional
	public void updateCompany(UserVO userVO) {

		if (userVO != null) {
//			Client client = this.clientDomainObjectManager.findClientByUserName(userVO.getStrUsrName());
			User user = null;

//			if (client.getUsers() != null && client.getUsers().size() > 0)
//				user = client.getUsers().iterator().next();
//			ClientCompanyVO clientVO = new ClientCompanyVO();
//			getMapper().map(client,clientVO);
//			userVO.setClient(clientVO);
			user = this.userDomainObjectManager.findUserByUserName(userVO.getStrUsrName());
			
			if (user != null)
				getMapper().map(userVO, user);
			
			this.userDomainObjectManager.update(user);
//			client.setUsers(new HashSet(Arrays.asList(user)));
//			this.clientDomainObjectManager.update(client);
		}

	}
	/**
	 * Description:
	 * findTakheesIdByUserName:	Method to Trakhees ID of a user
	 * 
	 * @param	strUserName String
	 * @return 	String	Trakhees ID
	 * 					   
	 */
	@Transactional(readOnly = true)
	public String findTakheesIdByUserName(String userName) {

		if (userName != null) {
			return this.clientDomainObjectManager.findTrakheesIdByUserName(userName);
		} else
			return null;
	}
	/**
	 * Description:
	 * findPersonAvailableRoleByUserName:	Method to find list of client roles that the Client can enroll for
	 * 
	 * @param	strUserName String
	 * @return 	List<{@link ClientRoleVO}>	Returns List of {@link ClientRoleVO}
	 * 					   
	 */
	@Transactional(readOnly = true)
	public List<ClientRoleVO> findPersonAvailableRoleByUserName(String strUserName) {

		Client client = this.clientDomainObjectManager.findClientByUserName(strUserName);
		// String strTrakheesId =
		// this.clientDomainObjectManager.findTrakheesIdByUserName(strUserName);
		String strTrakheesId = client.getCTrakheesId();
		String[] clientId = strTrakheesId.split("-");
		String clientType = null;
		List<String> roleIds = new ArrayList<String>();

		if (clientId[0].equals(ConstantsCommon.PERSON)) {
			clientType = ConstantsCommon.PERSON;

			List<SCClientPersonRoleVO> clientPersonRoleVOs = this.singleClientPersonDomainObjectManager
					.findSCPersonRoleByTrakheesId(client.getCTrakheesId());
			if(clientPersonRoleVOs != null){
				for (SCClientPersonRoleVO clientPersonRoleVO : clientPersonRoleVOs) {
					roleIds.add(clientPersonRoleVO.getCrId().toString());
				}
			}

		} else {

			clientType = ConstantsCommon.COMPANY;
			List<SCClientCompanyRoleVO> clientCompanyRoleVOs = this.singleClientCompanyDomainObjectManager
					.findSCCompanyRoleByTrakheesId(client.getCTrakheesId());
			if(clientCompanyRoleVOs != null){
				for (SCClientCompanyRoleVO clientCompanyRoleVO : clientCompanyRoleVOs) {
					roleIds.add(clientCompanyRoleVO.getCrId().toString());
				}
			}

		}

		/*
		 * for(ClientServiceRole clientServiceRole :
		 * client.getClientServiceRoles()){
		 * roleIds.add(clientServiceRole.getServiceRole
		 * ().getRoleId().toString()); }
		 */
		roleIds.add(ConstantsCommon.DEFAULT_SERVICE_ROLE_COMPANY_ID);

		List<TTscClientRole> roleVOs = this.utilityDomainObjectManager.getAvailableClientRoleList(clientType, roleIds);
		List<ClientRoleVO> clientRoleVOList = new ArrayList<ClientRoleVO>();

		ClientRoleVO clientRoleVO;

		List<ClientRoleReq> clientRoleReqs = this.clientDomainObjectManager
				.findClientRoleReqByTrakheesId(client.getCTrakheesId());

		if (roleVOs != null) {
			for (TTscClientRole scClientPersonRoleVO : roleVOs) {
				// To check if the role is already assigned we restrict that
				// role to
				clientRoleVO = new ClientRoleVO();

				if (null != scClientPersonRoleVO) {
					boolean alreadyRequested = false;

					// If role is already requested restricting it
					if (clientRoleReqs != null && clientRoleReqs.size() > 0) {
						for (ClientRoleReq clientRoleReq : clientRoleReqs) {
							if (clientRoleReq.getRoleId().compareTo(Long.parseLong(scClientPersonRoleVO.getCrId())) == 0) {
								alreadyRequested = true;
								break;
							}
						}
					}

					if (alreadyRequested)
						continue;

					getMapper().map(scClientPersonRoleVO, clientRoleVO);
				}

				clientRoleVOList.add(clientRoleVO);
			}
			/*
			 * List<TTscClientRole> roleVOs =
			 * this.utilityDomainObjectManager.getClientRoleList(clientType);
			 * 
			 * List<ClientRoleVO> clientRoleVOList = new
			 * ArrayList<ClientRoleVO>(); ClientRoleVO clientRoleVO;
			 * 
			 * for (TTscClientRole scClientPersonRoleVO : roleVOs) { // To check
			 * if the role is already assigned we restrict that role to // be
			 * displayed boolean found = false;
			 * 
			 * for (ClientServiceRole clientServiceRole :
			 * client.getClientServiceRoles()) {
			 * 
			 * if (clientServiceRole.getCsRoleId() != null) { if
			 * (scClientPersonRoleVO
			 * .getCrId().equals(clientServiceRole.getServiceRole
			 * ().getRoleId().toString())) { found = true; break;
			 * 
			 * } } }
			 * 
			 * if (!found) { clientRoleVO = new ClientRoleVO(); if (null !=
			 * scClientPersonRoleVO) getMapper().map(scClientPersonRoleVO,
			 * clientRoleVO); clientRoleVOList.add(clientRoleVO); } }
			 */

			return clientRoleVOList;
		} else
			return null;

	}
	/*
	 * Description:
	 * getNextApplicationId:	Method to getNextApplicationId
	 * 
	 * @param	String
	 * @return	String
	 */
	public String getNextApplicationId(){
	    return this.appMetaDataDomainObjectManager.getNextApplicationId();
	}
	/**
	 * Description:
	 * addClientRoleReq:	Method to create Client Role Request
	 * 
	 * @param	strUserName String
	 * @param	roleIds	List<Long> List of role Ids
	 * @param	appMetaDataVO	 AppMetaDataDetailVO Contains other application information
	 * @return 	String	Returns Client Reference Number
	 * 					   
	 */
	@Transactional
	public String addClientRoleReq(String strUserName, List<Long> roleIds, AppMetaDataDetailVO appMetaDataVO){
		Client client = this.clientDomainObjectManager.findClientByUserName(strUserName);
		User user = this.userDomainObjectManager.findUserByUserName(strUserName);
		AppMetaData appMetaData = new AppMetaData();
		ae.pcfc.etks.online.common.domain.Process process = processDomainObjectManager.getProcessByProcessAndStepCode(
				appMetaDataVO.getProcessCode().getProcessCode(), appMetaDataVO.getStrProcessStep());
		appMetaData.setProcess(process);
		getMapper().map(appMetaDataVO, appMetaData);
		//Below code added for testing
		//appMetaData.setApplicationId("10000060");
		
		appMetaData.setClientId(client.getCId());
		appMetaData.setUserId(user.getUId());
		
		ClientRoleReq clientRoleReq;

		for (Long roleId : roleIds) {

			clientRoleReq = new ClientRoleReq();
			clientRoleReq.setClient(client);
			clientRoleReq.setRoleId(roleId);
			clientRoleReq.setApplicationId(appMetaData.getApplicationId());

			if (this.clientDomainObjectManager.findClientRoleReqByClientAndRoleId(client.getCId(), roleId) == null) {

				this.clientDomainObjectManager.addClientRoleReq(clientRoleReq);
			} else {
				throw new DuplicateRoleRequestException(this.singleClientRoleObjectManager.getClientRoleByRoleId(
						roleId.toString()).getCrDesc());
			}
		}

		appMetaDataDomainObjectManager.add(appMetaData);

		return appMetaData.getClientRefNo();

	}
	/**
	 * Description:
	 * findClientReqRoleByApplicationId:	Method to find Client Role Requests by Application ID
	 * 
	 * @param	applicationId String
	 * @return 	List<ClientRoleVO>
	 * 					   
	 */
	@Transactional(readOnly = true)
	public List<ClientRoleVO> findClientReqRoleByApplicationId(String applicationId) {

		List<ClientRoleReq> clientRoleReqs = this.clientDomainObjectManager.findClientRolReqByApplicationId(applicationId);
		List<ClientRoleVO> clientRoleVOs = new ArrayList<ClientRoleVO>();

		if (clientRoleReqs != null && clientRoleReqs.size() > 0) {
			ClientRoleVO clientRoleVO;

			for (ClientRoleReq clientRoleReq : clientRoleReqs) {
				clientRoleVO = new ClientRoleVO();
				TTscClientRole tscClientRole = this.singleClientRoleObjectManager.getClientRoleByRoleId(clientRoleReq.getRoleId()
						.toString());
				getMapper().map(tscClientRole, clientRoleVO);

				clientRoleVOs.add(clientRoleVO);
			}
		}
		return (clientRoleVOs != null && clientRoleVOs.size() > 0) ? clientRoleVOs : null;

	}
	/**
	 * reviewClientRoleRequest
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#reviewClientRoleRequest(ae.pcfc.etks.online.common.vo.AdminApprovalVO)
	 * 
	 */
	@Transactional
	public ClientRoleCompleteStepVO reviewClientRoleRequest(AdminApprovalVO adminApprovalVO, List<ServiceRole> returnServiceRoles) {

		AppMetaData appMetaData = appMetaDataDomainObjectManager.findByPrimaryKeyProcessAndStepCode(adminApprovalVO
				.getStrApplicationId().toString(), adminApprovalVO.getProcessCode().getProcessCode(), adminApprovalVO.getStrStepName());

		if (appMetaData != null) {
			/************ Storing Meta Data in Tables ***********************/
            	    	if(appMetaDataDomainObjectManager.validateAppMetaDataWithStep(appMetaData,adminApprovalVO.getStrStepName())){
        	    	    throw new InvalidInputException();
        	    	}		    
			String wfStatusEn = appMetaData.getWfStatusEn();
			String wfStatusAr = appMetaData.getWfStatusAr();
			
			getMapper().map(adminApprovalVO, appMetaData);
			
			appMetaData.setWfStatusEn(wfStatusEn);
			appMetaData.setWfStatusAr(wfStatusAr);
			
			this.appMetaDataDomainObjectManager.updateAppMetaDataWithActionTaken(appMetaData, adminApprovalVO.getStrStepName());
			/************** End Store Meta Date ***************************/
			ClientRoleCompleteStepVO completeStepVO = getCompleteStepVO(adminApprovalVO, appMetaData);

			if(clientRoleWF.getFinDeptStepName().equalsIgnoreCase(adminApprovalVO.getStrStepName()) && adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by Finance department, send the approval message to the Ultimus alone and update the application request in the DB as approved
					List<ServiceRole> tempServiceRoles= addRequestedRoles(adminApprovalVO);
					if(tempServiceRoles != null){
						returnServiceRoles.addAll(tempServiceRoles);
					}
        			appMetaData.setWfStatus(ConstantsCommon.APPROVE);
        			appMetaData.setWfStatusEn(adminApprovalVO.getStrStatusEn());
        			appMetaData.setWfStatusAr(adminApprovalVO.getStrStatusAr());
        			clientRoleWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_APPROVE, adminApprovalVO.getStrUserNotification());
			}else if(adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by any other departments, send the approval message to the Ultimus alone
			    	clientRoleWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_APPROVE, adminApprovalVO.getStrUserNotification());
			}else if(adminApprovalVO.getStrActionType().equals(ConstantsCommon.REJECT)){
			    	// If Rejected, update the application request in DB as rejected and send the rejection message to the Ultimus
			    	appMetaData.setWfStatus(ConstantsCommon.REJECT);
				appMetaData.setWfStatusEn(adminApprovalVO.getStrStatusEn());
				appMetaData.setWfStatusAr(adminApprovalVO.getStrStatusAr());
				clientRoleWF.updateCompleteStepVO(completeStepVO, adminApprovalVO.getStrStepName(), ConstantsCommon.WORK_FLOW_STATUS_REJECT, adminApprovalVO.getStrUserNotification());
			}
			appMetaDataDomainObjectManager.update(appMetaData);
			//clientRoleWF.completeNonClientWFStep(completeStepVO);
			return completeStepVO;
		}
		
		return null;

	}


	/**
	 * addClientRolesToUser
	 * To add the requested roles to the Client in TSC and add the roles to the Client's user in Online DB 
	 * @param adminApprovalVO
	 * void
	 */
	private List<ServiceRole> addRequestedRoles(AdminApprovalVO adminApprovalVO) {
	    List<ClientRoleReq> clientRoleReqs = this.clientDomainObjectManager.findClientRolReqByApplicationId(adminApprovalVO.getStrApplicationId());
	    List<ServiceRole> serviceRoles = new ArrayList<ServiceRole>();
	    if(clientRoleReqs != null){
		for (ClientRoleReq clientRoleReq : clientRoleReqs) {
			/************* Storing the Client Role on TSC **********************/
			if (clientRoleReq.getClient().getCType().equals(ConstantsCommon.PERSON))
				this.singleClientPersonDomainObjectManager.addSCPersonRole(clientRoleReq.getRoleId(), clientRoleReq
						.getClient().getCTrakheesId(), StringUtils.remove(adminApprovalVO.getStrUserName(),
						ConstantsWF.USER_PREFIX));
			else
				this.singleClientCompanyDomainObjectManager.addSCCompanyRole(clientRoleReq.getRoleId(), clientRoleReq
						.getClient().getCTrakheesId(), StringUtils.remove(adminApprovalVO.getStrUserName(),
						ConstantsWF.USER_PREFIX));
			/************* End Storing the Client Role on TSC ******************/

			/************* Storing the Client Service Role ******************/
			
			List<ServiceRole> tempServiceRoles = this.serviceDomainObjectManager.findAvailableServiceRoleByRoleIdForClient(clientRoleReq.getRoleId(), clientRoleReq.getClient() );
			addServiceRolesToUsers( clientRoleReq.getClient(), tempServiceRoles);
			
			/************* End Storing Service Security for User ******************/
			serviceRoles.addAll(tempServiceRoles);
			}
	    }
	    return serviceRoles;
	    
	}

	/**
	 * addClientServiceRoles
	 * To add the Service Roles to the users of a client in Online DB
	 * @param client 
	 * 
	 * @param serviceRoles
	 * void
	 */
	private void addServiceRolesToUsers(Client client, List<ServiceRole> serviceRoles) {
	    if (serviceRoles != null) {
		ClientServiceRole clientServiceRole;

		for (ServiceRole serviceRole : serviceRoles) {
			clientServiceRole = new ClientServiceRole();
			clientServiceRole.setClient(client);
			clientServiceRole.setServiceRole(serviceRole);

			this.clientDomainObjectManager.addClientServiceRole(clientServiceRole);

		}

		/************* End Storing Client Service Role ******************/

		/************* Storing Service Security for User ******************/
		Set<User> users = client.getUsers();

		UserServiceSecurity userServiceSecurity;

		for (User user : users) {

			// For User Service Security

			for (ServiceRole serviceRole : serviceRoles) {
				if (serviceRole.getService() != null && serviceRole.getService().getServiceDefault() != null
						&& serviceRole.getService().getServiceDefault().equals("Y")) {

					userServiceSecurity = new UserServiceSecurity();
					userServiceSecurity.setServiceRole(serviceRole);
					userServiceSecurity.setUsSecurityUsername(user.getUUsername());
					//userServiceSecurity.setUsSecurityUserType(client.getCType());
					userServiceSecurity.setUsSecurityUserType(user.getUType());

					this.userServiceSecurityDomainObjectManager.add(userServiceSecurity);

				}

			}
		}
	}
	    
	}

	/**
	 * getCompleteStepVO
	 * To get the CompleteStepVO with the values populated
	 * @param adminApprovalVO
	 * @param appMetaData
	 * @return
	 * ClientRoleCompleteStepVO
	 */
	private ClientRoleCompleteStepVO getCompleteStepVO(AdminApprovalVO adminApprovalVO, AppMetaData appMetaData) {
		ClientRoleCompleteStepVO completeStepVO = new ClientRoleCompleteStepVO();
		completeStepVO.setgApplicationID(adminApprovalVO.getStrApplicationId());
		completeStepVO.setgClientReference(appMetaData.getClientRefNo());
		completeStepVO.setStrStepName(adminApprovalVO.getStrStepName());
		completeStepVO.setStrUserName(adminApprovalVO.getStrUserName());

		if (appMetaData.getUserId() != null) {
			User user = this.userDomainObjectManager.findByPrimaryKey(appMetaData.getUserId().toString());
			if (user != null) {
				completeStepVO.setgName(user.getUNameEng());
				completeStepVO.setgEmail(user.getUEmail());
			}

		}
		completeStepVO.setnIncidentNumber(Integer.parseInt(adminApprovalVO.getStrIncidentNo()));
		return completeStepVO;
	}

	/**
	 * Description:
	 * findTrakheesIdByApplicationId:	Method to find Trakhees Id by Application ID
	 *
	 * @param	id - String
	 * @return	String - Trakhees Id
	 * 
	 */	
	@Transactional(readOnly = true)
	public String findTrakheesIdByApplicationId(String id) {
		AppMetaData appMetaData = this.appMetaDataDomainObjectManager.findByPrimaryKey(id);

		if (appMetaData != null) {
			Client client = this.clientDomainObjectManager.findByPrimaryKey(appMetaData.getClientId().toString());
			if (client != null)
				return client.getCTrakheesId().toString();
			else
				return null;
		} else
			return null;
	}
	/**
	 * Description:
	 * findClientUserByEmail:	Method to find Client Object by email address
	 *
	 * @param	email - String
	 * @return	TrakheesIdAndPINVO
	 * 
	 */	
	@Transactional(readOnly = true)
	public Client findClientUserByEmail(String email) {

		return this.clientDomainObjectManager.findClientUserByEmail(email);
	}
	/**
	 * Description:
	 * findTrakheesIdAndPinByEmail:	Method to find Trakhees ID and PIN by email address
	 *
	 * @param	email - String
	 * @return	TrakheesIdAndPINVO
	 * 
	 */	
	@Transactional
	public TrakheesIdAndPINVO findTrakheesIdAndPinByEmail(String email) {

		return this.singleClientCompanyDomainObjectManager.findTrakheesIdAndPinByEmail(email);
	}
	/**
	 * Description:
	 * validateRegisterPerson:	Utility method to validate the Company Registered request
	 * Checks whether the username and email already exists in the approved and in progress requests.  
	 *
	 * @param	clientPersonReqVO	String	Contains the information about the Client Person request obtained from the front end
	 * @throws	DuplicateUserNameException - in case of username already exists
	 * 			DuplicateUserEmailException - in case of email address already exists
	 * @return	- returns true on success
	 * 
	 */	
	@Transactional(readOnly = true)
	public boolean validateRegisterPerson(ClientPersonReqVO clientPersonReqVO) {
		if (this.userDomainObjectManager.findClientAdminByTrakheesId(clientPersonReqVO.getStrTrakheesId()) == null
				&& this.userReqDomainObjectManager.validateByPropertyName("UTrakheesId",clientPersonReqVO.getStrTrakheesId())) {
			if (this.userDomainObjectManager.findUserByUserName(clientPersonReqVO.getStrUserName()) == null
					&& this.userReqDomainObjectManager.validateByPropertyName("UReqUsername",clientPersonReqVO.getStrUserName())) {
	
	/*			if (this.userDomainObjectManager.findUserByEmail(clientPersonReqVO.getStrEmailAddress()) == null
						&& this.userReqDomainObjectManager.validateByPropertyName("UReqEmail",clientPersonReqVO.getStrEmailAddress())) {
	
				} else {
					throw new DuplicateUserEmailException(clientPersonReqVO.getStrEmailAddress());
				}
	*/
			} else {
				throw new DuplicateUserNameException(clientPersonReqVO.getStrUserName());
			}
		} else {
			throw new DuplicateClientAdminException(clientPersonReqVO.getStrTrakheesId());
		}
		
		return true;
	}
	/**
	 * Description:
	 * validateRegisterCompany:	Utility method to validate the Company Registered request
	 * Checks whether the username and email already exists in the approved and in progress requests.  
	 *
	 * @param	clientCompanyReqVO - ClientCompanyReqVO - Contains the information about the Client Company request obtained from the front end
	 * @throws	DuplicateUserNameException - in case of username already exists
	 * 			DuplicateUserEmailException - in case of email address already exists
	 * @return	- returns true on success
	 * 
	 */	
	@Transactional(readOnly = true)
	public boolean validateRegisterCompany(ClientCompanyReqVO clientCompanyReqVO) {
/*		List<User> users = this.userDomainObjectManager.findUsersByTrakheesId(clientCompanyReqVO.getStrTrakheesId());
		if(users != null){
			for(User user : users){
				if(ConstantsCommon.COMPANY_ADMIN.equalsIgnoreCase(user.getUType()) && ConstantsCommon.ACTIVE.equalsIgnoreCase(user.getUStatus())){
					throw new DuplicateClientAdminException(clientCompanyReqVO.getStrTrakheesId());
				}
			}
		}
*/		if (this.userDomainObjectManager.findClientAdminByTrakheesId(clientCompanyReqVO.getStrTrakheesId()) == null
		&& this.userReqDomainObjectManager.validateByPropertyName("UTrakheesId",clientCompanyReqVO.getStrTrakheesId())) {
				if (this.userDomainObjectManager.findUserByUserName(clientCompanyReqVO.getStrUserName()) == null
					&& this.userReqDomainObjectManager.validateByPropertyName("UReqUsername",clientCompanyReqVO.getStrUserName())) {
	
					/*if (this.userDomainObjectManager.findUserByEmail(clientCompanyReqVO.getStrEmailAddress()) == null
						&& this.userReqDomainObjectManager.validateByPropertyName("UReqEmail",clientCompanyReqVO.getStrEmailAddress())) {
	
					} else {
						throw new DuplicateUserEmailException(clientCompanyReqVO.getStrEmailAddress());

					}*/
	
				} else {
					throw new DuplicateUserNameException(clientCompanyReqVO.getStrUserName());
				}
				
		} else {
			throw new DuplicateClientAdminException(clientCompanyReqVO.getStrTrakheesId());
		}
		return true;
	}
	/**
	 * Description:
	 * updateWorkflowIncidentVO:	Method to update the LaunchIncidentVO based on the client roles the Service.
	 * This method finds the client roles of the Service, find its corresponding departments and sets the department flag in the LaunchIncidentVO
	 * By default, Finance Department is set to mandatory approval department, irrespective of the service role of the service 
	 * @author Dicetek.Ismail
	 * @param	LaunchIncidentVO - The workflow incident object which needs to be updated with the approval departments
	 * @param	- List<String> - List of String objects which are client role ids 
	 * 
	 */	
	@Transactional(readOnly = true)
	public void updateWorkflowIncidentVO(LaunchIncidentVO launchIncidVO, List<String> clientRoles){
		if(launchIncidVO != null && clientRoles != null ){
			List<TTscClientRoleToDepartmentMap> departments = this.utilityDomainObjectManager.getDepartmentsByRoleIds(clientRoles);
			if(departments == null){
				departments = new ArrayList<TTscClientRoleToDepartmentMap>();
			}

			List<String> strDepartments = new ArrayList<String>();
			List<WorkflowDepartment> wfDepartments = new ArrayList<WorkflowDepartment>();
			for(TTscClientRoleToDepartmentMap deptMap : departments){
				TTscDepartments dept = deptMap.getDepartment();
				strDepartments.add(dept.getDeptCode().toUpperCase());
				wfDepartments.add(WorkflowDepartment.getWorkflowDepartmentfromString(dept.getDeptCode()));
			}
			launchIncidVO.setgApprovalFIN(ConstantsCommon.SET_VALUE);
			if(strDepartments.contains(WorkflowDepartment.CED.getCode())){
				launchIncidVO.setgApprovalCED(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalCED(ConstantsCommon.UNSET_VALUE);
			}
			if(strDepartments.contains(WorkflowDepartment.CLD.getCode())){
				launchIncidVO.setgApprovalCLD(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalCLD(ConstantsCommon.UNSET_VALUE);
			}
			if(strDepartments.contains(WorkflowDepartment.EHS.getCode())){
				launchIncidVO.setgApprovalEHS(ConstantsCommon.SET_VALUE);
			}else{
				launchIncidVO.setgApprovalEHS(ConstantsCommon.UNSET_VALUE);
			}
		}
	}
	@Transactional
	public void undoReviewClientRoleRequest(AdminApprovalVO adminApprovalVO, List<ServiceRole> returnServiceRoles) {
		AppMetaData appMetaData = appMetaDataDomainObjectManager.findByPrimaryKeyProcessAndStepCode(adminApprovalVO
				.getStrApplicationId().toString(), adminApprovalVO.getProcessCode().getProcessCode(), adminApprovalVO.getStrStepName());

		if (appMetaData != null) {
			adminApprovalVO.setStrApplnStatus(ConstantsCommon.IN_PROGRESS);
			getMapper().map(adminApprovalVO, appMetaData);
			
			this.appMetaDataDomainObjectManager.undoUpdateAppMetaDataWithActionTaken(appMetaData, adminApprovalVO.getStrStepName());

			if(clientRoleWF.getFinDeptStepName().equalsIgnoreCase(adminApprovalVO.getStrStepName()) && adminApprovalVO.getStrActionType().equals(ConstantsCommon.APPROVE)){
			    	// If Approved by Finance department, send the approval message to the Ultimus alone and update the application request in the DB as approved
			    	undoAddRequestedRoles(adminApprovalVO, returnServiceRoles);
			}
			appMetaData.setWfStatus(ConstantsCommon.IN_PROGRESS);
			appMetaData.setWfStatusEn(adminApprovalVO.getStrInProgressStatusEn());
			appMetaData.setWfStatusAr(adminApprovalVO.getStrInProgressStatusAr());
			appMetaDataDomainObjectManager.update(appMetaData);
		}
	}

	private void undoAddRequestedRoles(AdminApprovalVO adminApprovalVO, List<ServiceRole> returnServiceRoles) {
	    List<ClientRoleReq> clientRoleReqs = this.clientDomainObjectManager.findClientRolReqByApplicationId(adminApprovalVO.getStrApplicationId());
	    if(clientRoleReqs != null){
		for (ClientRoleReq clientRoleReq : clientRoleReqs) {
			/************* Storing the Client Role on TSC **********************/
			if (clientRoleReq.getClient().getCType().equals(ConstantsCommon.PERSON))
				this.singleClientPersonDomainObjectManager.removeSCPersonRole(clientRoleReq.getRoleId(), clientRoleReq
						.getClient().getCTrakheesId(), StringUtils.remove(adminApprovalVO.getStrUserName(),
						ConstantsWF.USER_PREFIX));
			else
				this.singleClientCompanyDomainObjectManager.removeSCCompanyRole(clientRoleReq.getRoleId(), clientRoleReq
						.getClient().getCTrakheesId(), StringUtils.remove(adminApprovalVO.getStrUserName(),
						ConstantsWF.USER_PREFIX));
			/************* End Storing the Client Role on TSC ******************/

			/************* Storing the Client Service Role ******************/
			
			//List<ServiceRole> serviceRoles = this.serviceDomainObjectManager.findServiceRoleByRoleId(clientRoleReq.getRoleId());
			undoAddServiceRolesToUsers( clientRoleReq.getClient(), returnServiceRoles);
			
			/************* End Storing Service Security for User ******************/

			}
	    }
		
	}
	/**
	 * undoAddServiceRolesToUsers
	 * To undo the addition the Service Roles to the users of a client in Online DB
	 * @param client 
	 * 
	 * @param serviceRoles
	 * void
	 */
	private void undoAddServiceRolesToUsers(Client client, List<ServiceRole> serviceRoles) {
	    if (serviceRoles != null) {
	    	for (ServiceRole serviceRole : serviceRoles) {
	    		List<ClientServiceRole> clientServiceRoles = this.serviceDomainObjectManager.findServiceRoleByClientAndRoleId(client,serviceRole.getSrId());
				if(clientServiceRoles != null){
					for(ClientServiceRole csr : clientServiceRoles){
							this.clientDomainObjectManager.delete(csr);
					}
				}
	    	}
			Set<User> users = client.getUsers();
	
			UserServiceSecurity userServiceSecurity;
			Set<UserServiceSecurity> ussSet = new HashSet<UserServiceSecurity>();
			for (User user : users) {
				// For User Service Security
				for (ServiceRole serviceRole : serviceRoles) {
					if (serviceRole.getService() != null && serviceRole.getService().getServiceDefault() != null
							&& serviceRole.getService().getServiceDefault().equals("Y")) {
	
						userServiceSecurity = new UserServiceSecurity();
						userServiceSecurity.setServiceRole(serviceRole);
						userServiceSecurity.setUsSecurityUsername(user.getUUsername());
						//userServiceSecurity.setUsSecurityUserType(client.getCType());
						userServiceSecurity.setUsSecurityUserType(user.getUType());
	
						List<UserServiceSecurity> ussList = this.userServiceSecurityDomainObjectManager.findUserServiceSecurity(userServiceSecurity);
						if(ussList != null){
						    ussSet.addAll(ussList);
						}
					}
	
				}
			}
			for(UserServiceSecurity uss : ussSet){
				this.userServiceSecurityDomainObjectManager.delete(uss);
			}
		}
	}
	@Transactional
	public void updatePersonWorkflowIncidentVO(LaunchIncidentVO launchIncidVO, String strTrakheesId) {
		List<SCClientPersonRoleVO> clientRoles = this.singleClientPersonDomainObjectManager.findSCPersonRoleByTrakheesId(strTrakheesId);
		List<String> strClientRoles = new ArrayList<String>();
		if(clientRoles != null){
			for(SCClientPersonRoleVO roleId : clientRoles){
				strClientRoles.add(roleId.getCrId().toString());
			}
		}

		updateWorkflowIncidentVO(launchIncidVO, strClientRoles);
	}
	@Transactional
	public void updateCompanyWorkflowIncidentVO(LaunchIncidentVO launchIncidVO, String strTrakheesId) {
		List<SCClientCompanyRoleVO> clientRoles = this.singleClientCompanyDomainObjectManager.findSCCompanyRoleByTrakheesId(strTrakheesId);
		List<String> strClientRoles = new ArrayList<String>();
		if(clientRoles != null){
			for(SCClientCompanyRoleVO roleId : clientRoles){
				strClientRoles.add(roleId.getCrId().toString());
			}
		}
		updateWorkflowIncidentVO(launchIncidVO, strClientRoles);
	}

	/**
	 * findTrakheesIdAndPinByLicenseInfo
	 * 
	 * @see ae.pcfc.etks.online.common.facade.ClientRegistrationFacade#findTrakheesIdAndPinByLicenseInfo(ae.pcfc.etks.online.common.vo.SearchCriteriaCompanyVO)
	 * 
	 */
	@Transactional(readOnly = true)
	public TrakheesIdAndPINVO findTrakheesIdAndPinByLicenseInfo(SearchCriteriaCompanyVO searchCriteriaCompanyVO) {
	    List<TTscClientCompany> companies = this.singleClientCompanyDomainObjectManager.searchCompany(searchCriteriaCompanyVO);
	    if(companies != null && companies.size() > 0){
		if(companies.size() > 1 ){
		    TTscClientCompany ttscClientCompany = companies.get(0);  
		    TTscLicIssuingAuthority authority = this.utilityDomainObjectManager.getLicIssuingAuthorityByCode(searchCriteriaCompanyVO.getLicenseIssuingAuth());
		    throw new TscClientLicenseInfoException( authority.getIaDesc(), authority.getIaDescArb(), searchCriteriaCompanyVO.getLicenseNumber());
		}
		TrakheesIdAndPINVO trakheesIdAndPINVO = new TrakheesIdAndPINVO();
		TTscClientCompany ttscClientCompany = companies.get(0);  
		trakheesIdAndPINVO.setStrTrakheesID(ttscClientCompany.getCcTrakheesId());
		trakheesIdAndPINVO.setStrTrakheesPIN(ttscClientCompany.getPinCode());
		trakheesIdAndPINVO.setStrEmail(ttscClientCompany.getCcEmail());
		return trakheesIdAndPINVO;
	    }
	    return null;
	}
	@Transactional
	public List<ClientRoleVO> findCurrentRolesByUserName(String strUserName) {
		List<ClientRoleVO> clientRoleVOList = new ArrayList<ClientRoleVO>();
		Client client = this.clientDomainObjectManager.findClientByUserName(strUserName);
		if(client==null){
			return null;
		}
		String strTrakheesId = client.getCTrakheesId();
		String[] clientId = strTrakheesId.split("-");

		if (clientId[0].equals(ConstantsCommon.PERSON)) {
			List<SCClientPersonRoleVO> clientPersonRoleVOs = this.singleClientPersonDomainObjectManager
					.findSCPersonRoleByTrakheesId(client.getCTrakheesId());
			if(clientPersonRoleVOs != null){
				for (SCClientPersonRoleVO clientPersonRoleVO : clientPersonRoleVOs) {
					ClientRoleVO clientRoleVO = new ClientRoleVO();
					this.getMapper().map(clientPersonRoleVO, clientRoleVO);
					clientRoleVOList.add(clientRoleVO);
				}
			}

		} else {
			List<SCClientCompanyRoleVO> clientCompanyRoleVOs = this.singleClientCompanyDomainObjectManager
					.findSCCompanyRoleByTrakheesId(client.getCTrakheesId());
			if(clientCompanyRoleVOs != null){
				for (SCClientCompanyRoleVO clientCompanyRoleVO : clientCompanyRoleVOs) {
					ClientRoleVO clientRoleVO = new ClientRoleVO();
					this.getMapper().map(clientCompanyRoleVO, clientRoleVO);
					clientRoleVOList.add(clientRoleVO);
				}
			}

		}

		return clientRoleVOList;
	}

	public List<SCCompanyVO> findCompany(SearchCriteriaCompanyVO searchCriteriaCompanyVO) {
		List<TTscClientCompany> companies = this.singleClientCompanyDomainObjectManager.searchCompany(searchCriteriaCompanyVO);
		List<SCCompanyVO> companyVOs = new ArrayList<SCCompanyVO>();
	    if(companies != null && companies.size() > 0){
	    	for(TTscClientCompany ttscClientCompany:companies){
	    		SCCompanyVO scCompanyVO = new SCCompanyVO();
	    		this.getMapper().map(ttscClientCompany, scCompanyVO);
	    		companyVOs.add(scCompanyVO);
	    	}
	    	return companyVOs;
	    }
	    return null;
	}

	public List<SCPersonVO> findPerson(SearchCriteriaPersonVO searchCriteriaPersonVO) {
		List<TTscClientPerson> persons = this.singleClientPersonDomainObjectManager.searchPerson(searchCriteriaPersonVO);
		List<SCPersonVO> personVOs = new ArrayList<SCPersonVO>();
	    if(persons != null && persons.size() > 0){
	    	for(TTscClientPerson ttscClientPerson:persons){
	    		SCPersonVO scPersonVO = new SCPersonVO();
	    		this.getMapper().map(ttscClientPerson, scPersonVO);
	    		personVOs.add(scPersonVO);
	    	}
	    	return personVOs;
	    }
	    return null;
	}	
}
